home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGNG_C
/
TURBOCU1.LZH
/
HSORT.C
< prev
next >
Wrap
Text File
|
1987-09-05
|
8KB
|
302 lines
/***********************************************************************/
/* HSORT(): Heap Sort function. */
/* See the function declaration for calling information. */
/* Set STANDALONE != 0 to compile a shell to test the sucker; */
/* to compile just hsort() and its supporting functions, set */
/* STANDALONE = 0. */
/* DEBUG determines how much debugging info is displayed; 0 is none. */
/* TRACE determines what level of tracing information is displayed; */
/* 0 is none. */
/* Function is by Bruce Feist; please contact me on CompuServe with */
/* a message on BORPRO or through EASYPLEX if you have any */
/* questions or problems. */
/* Feel free to make use of this code in your own programs. */
/***********************************************************************/
#define DEBUG 0
#define STANDALONE 0
#define TRACE 0
#include <stdio.h>
#include <process.h>
#include <alloc.h>
#include <stdlib.h>
#include <mem.h>
static void pascal swap (unsigned int, unsigned int);
static void pascal buildheap (void);
static void pascal heapify (unsigned int, unsigned int);
void hsort (void *, unsigned int, unsigned int, int (*)());
#if STANDALONE
static int int_compare (int *, int *);
static void showarray (int *, unsigned int, unsigned int);
void
main()
{
unsigned int n_entries, entry_num;
int *entries;
printf ("How many entries do you wish to sort? ");
scanf ("%d", &n_entries);
entries = (int *) malloc (n_entries * sizeof(int));
for (entry_num = 0; entry_num < n_entries; entry_num++)
{
printf ("Enter #%d: ", entry_num);
scanf ("%d", entries + entry_num);
}
printf ("\n");
hsort (entries, n_entries, sizeof (int), int_compare);
showarray (entries, 0, n_entries - 1);
exit (0);
}
int
int_compare (i, j)
int *i, *j;
{
return (*i - *j);
}
void
showarray(base, bot, top)
int *base;
unsigned int bot, top;
{
unsigned int i;
for (i=bot; i<=top; i++)
printf("%4d", base[i]);
printf ("\n");
}
#endif /* STANDALONE */
static int (*static_compare) (void *, void *), static_width, static_n_elements;
static void *temp_element, *static_base;
void
hsort(base, n_elements, element_width, compare)
/***************************************************************************/
/* Heap Sort routine -- similar in calling sequence to standard 'qsort()' */
/* Base is a pointer to an array */
/* n_elements is the number of elements in the array */
/* element_width is the width of each element in bytes */
/* compare is a function of two pointers (each to an element of the array) */
/* returning a negative value if the first is smaller, a positive value */
/* if the second is smaller, or 0 if they should be sorted the same. */
/* Warning! This function will halt your program if it can't allocate */
/* element_width bytes using malloc(). */
/***************************************************************************/
void *base;
unsigned int n_elements, element_width;
int (*compare)();
{
register unsigned int i;
#if TRACE >= 1
printf("hsort(base at %lX, %u elements, width %u, compare at %ld)\n",
(long) base, n_elements, element_width, (long) compare);
#endif
/* this lets us reference elements of array as 1 to n */
(char *) base -= element_width;
/* The following assignments to static variables reduce the */
/* overhead of subroutine calls later. */
static_width = element_width;
static_compare = compare;
static_n_elements = n_elements;
static_base = base;
temp_element = malloc (element_width);
if (temp_element == NULL)
{
fputs ("Unable to allocate room for a temporary element in hsort().\n",
stderr);
exit (1);
}
buildheap ();
for (i = n_elements; i>1; i--)
{
swap (1, i);
heapify (1, i-1);
}
free (temp_element);
}
static void pascal
swap (i, j)
unsigned int i,j;
{
register int temp_int;
long temp_long;
#if TRACE >= 2
printf("swap (i=%d, j=%d) called.\n",i,j);
#endif
switch (static_width)
{
case sizeof (int): temp_int = ((int *) static_base) [i];
((int *) static_base) [i] = ((int *) static_base) [j];
((int *) static_base) [j] = temp_int;
break;
case sizeof(long): temp_long = ((long *) static_base) [i];
((long *) static_base) [i] = ((long *) static_base) [j];
((long *) static_base) [j] = temp_long;
break;
case sizeof(char): temp_int = ((char *) static_base) [i];
((char *) static_base) [i] = ((char *) static_base) [j];
((char *) static_base) [j] = (char) temp_int;
break;
default: memcpy (temp_element,
(char *) static_base + i*static_width,
static_width);
memcpy ((char *) static_base + i*static_width,
(char *) static_base + j*static_width,
static_width);
memcpy ((char *) static_base + j*static_width,
temp_element,
static_width);
break;
} /* end of switch */
#if TRACE >= 2
printf ("swap exited.\n");
#endif
}
static void pascal
buildheap()
{
register unsigned int element_number;
#if TRACE >= 2
printf("buildheap() called.\n");
#endif
for (element_number = static_n_elements >> 1;
element_number >= 1;
element_number--)
{
#if DEBUG >= 2
printf ("buildheap calls heapify (%d, %d).\n",
element_number, static_n_elements);
#endif
heapify(element_number, static_n_elements);
}
#if TRACE >= 2
printf ("buildheap exited.\n");
#endif
}
#define son1(i) (i << 1)
#define son2(i) ((i << 1) + 1)
#define pointer(i) ((char *) static_base + i * static_width)
#define child_count(i, j) \
(j > son1(i) \
? 2 \
: j < son1(i) \
? 0 \
: 1)
static void pascal
heapify (i,j)
unsigned int i, j;
{
/* The following are static to avoid recursive stack overhead */
static unsigned int son1i, son2i;
static void *pson1, *pson2, *pi;
static unsigned int k;
#if TRACE >= 3
printf("heapify(i=%d, j=%d) called.\n", i, j);
#endif
son1i = son1 (i);
son2i = son2 (i);
pson1 = pointer (son1i);
pson2 = pointer (son2i);
pi = pointer (i);
#if DEBUG >= 2
printf ("child_count (%d) = %d.\n", i, child_count(i, j));
#endif
switch (child_count (i, j))
{
case 0: break;
case 2: {
k = (*static_compare) (pson1, pson2) > 0 ? son1i : son2i;
if ((*static_compare) (pi, pointer (k)) < 0)
{
#if STANDALONE && DEBUG >= 1
printf ("heapify changes\n");
showarray (static_base, 1, static_n_elements);
#endif
swap (i, k);
heapify (k, j);
#if STANDALONE && DEBUG >= 1
printf ("into\n");
showarray (static_base, 1, static_n_elements);
#endif
}
break;
} /* end case */
case 1: if ((*static_compare) (pi, pson1) < 0)
{
#if STANDALONE && DEBUG >= 1
printf ("heapify changes\n");
showarray (static_base, 1, static_n_elements);
#endif
swap (i, son1i);
heapify (son1i, j);
#if STANDALONE && DEBUG >= 1
printf ("into\n");
showarray (static_base, 1, static_n_elements);
#endif
}
break;
} /* end of case */
#if TRACE >= 3
printf ("heapify exited.\n");
#endif
}